# Created by Gao Song on 2019-05-23

import pandas as pd
import time
from fucker.pos_management import PosManagement
from event.event_def import EVENT_POSITION, EVENT_ACCOUNT, EVENT_ALL_POSITIONS
from mysite.lqcon.managements import AccountManagement

from event import EventEngine
from core.factory import create_object


class BrokerAccountInfo:

    def __init__(self, gateway, with_pos=True):
        self.gateway = gateway
        self.pm = PosManagement()
        self.balance = None
        self.frozen = None
        self.available = None
        self.with_pos = with_pos
        self.all_pos = False

        self.gateway.event_engine.register(EVENT_POSITION, self.on_position)
        self.gateway.event_engine.register(EVENT_ACCOUNT, self.on_account)
        self.gateway.event_engine.register(EVENT_ALL_POSITIONS, self.on_all_pos)

        wait_time = 0
        while not gateway.td_api.query_ins:
            time.sleep(2)
            wait_time += 2
            if wait_time > 120:
                return
        print('td login:', self.gateway.td_api.login_status, 'md login:', self.gateway.md_api.login_status)
        if self.with_pos:
            print('查询持仓...')
            self.gateway.query_position()
            while not self.all_pos:
                time.sleep(1)
        print('查询资金...')
        self.gateway.query_account()
        while self.balance is None:
            time.sleep(1)

    def print_summary(self):
        print(f'balance: {self.balance:.0f}, available: {self.available:.0f}, used_pct: {(self.balance - self.available) / self.balance:.2%}')
        # print('balance:', self.balance, 'available:', self.available, 'frozen:', self.frozen, 'used_pct:', (self.balance - self.available) / self.balance)
        if self.with_pos:
            pos_res = pd.DataFrame(columns=['long', 'long_td', 'long_yd', 'short', 'short_td', 'short_yd'])
            print('broker pos:')
            for symbol, pos in self.pm.holdings.items():
                pos_res.loc[symbol] = pos.long_pos, pos.long_td, pos.long_yd, pos.short_pos, pos.short_td, pos.short_yd
            print(pos_res)

    def print_long_short_pos(self):
        pos_res = pd.DataFrame(columns=['long', 'long_td', 'long_yd', 'short', 'short_td', 'short_yd'])
        print('broker pos:')
        for symbol, pos in self.pm.holdings.items():
            if pos.long_pos > 0 and pos.short_pos > 0:
                pos_res.loc[symbol] = pos.long_pos, pos.long_td, pos.long_yd, pos.short_pos, pos.short_td, pos.short_yd
        print(pos_res)

    def on_all_pos(self, e):
        self.all_pos = True

    def on_account(self, e):
        self.balance = e.data.balance
        self.frozen = e.data.frozen
        self.available = e.data.available

    def on_position(self, e):
        self.pm.update_position(e.data)


def create_broker_info(account_name, with_pos=True):
    account = AccountManagement.get_account_by_name(account_name)
    event_engine = EventEngine()
    event_engine.start()
    gateway = create_object('gateway', account.gateway_type, event_engine, account_name)

    gateway.connect(account.connection_info)

    info = BrokerAccountInfo(gateway, with_pos)
    event_engine.stop()
    return info

def update_broker_info(account_name):
    info = create_broker_info(account_name, with_pos=False)
    AccountManagement.update_broker_info(account_name, info.balance, info.available)
